<!DOCTYPE html>
<html>
<head>
    <title>Physics Diagram</title>
    <style>
        body {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            margin: 0;
            background-color: #f0f0f0;
        }
        canvas {
            border: 1px solid #ccc;
            background-color: #fff;
        }
    </style>
</head>
<body>
    <canvas id="physicsCanvas" width="600" height="400"></canvas>
    <script>
        const canvas = document.getElementById('physicsCanvas');
        const ctx = canvas.getContext('2d');

        // --- Drawing Functions ---
        function drawArrow(ctx, fromX, fromY, toX, toY) {
            const headlen = 10;
            const dx = toX - fromX;
            const dy = toY - fromY;
            const angle = Math.atan2(dy, dx);
            ctx.beginPath();
            ctx.moveTo(fromX, fromY);
            ctx.lineTo(toX, toY);
            ctx.stroke(); 
            ctx.beginPath();
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headlen * Math.cos(angle - Math.PI / 6), toY - headlen * Math.sin(angle - Math.PI / 6));
            ctx.moveTo(toX, toY);
            ctx.lineTo(toX - headlen * Math.cos(angle + Math.PI / 6), toY - headlen * Math.sin(angle + Math.PI / 6));
            ctx.stroke();
        }

        // --- Style and Configuration ---
        ctx.lineWidth = 2;
        ctx.strokeStyle = 'black';
        ctx.fillStyle = 'black';
        ctx.textAlign = 'center';
        ctx.textBaseline = 'middle';

        // --- Coordinates ---
        const ground_y = 330;
        const wall_x = 570;
        
        // Large Block M
        const M_w = 420;
        const M_h = 150;
        const M_x = 50;
        const M_y = ground_y - M_h;

        // Small Block m
        const m_w = 70;
        const m_h = 50;
        const m_x = M_x + 300;
        const m_y = M_y - m_h;

        // --- Main Drawing ---

        // 1. Ground
        ctx.beginPath();
        ctx.moveTo(0, ground_y);
        ctx.lineTo(canvas.width, ground_y);
        ctx.stroke();

        // 2. Wall
        ctx.beginPath();
        ctx.moveTo(wall_x, ground_y);
        ctx.lineTo(wall_x, 100);
        ctx.stroke();
        // Wall hatches
        const originalLineWidth = ctx.lineWidth;
        ctx.lineWidth = 1;
        for (let y = 110; y < ground_y; y += 15) {
            ctx.beginPath();
            ctx.moveTo(wall_x, y);
            ctx.lineTo(wall_x + 10, y - 10);
            ctx.stroke();
        }
        ctx.lineWidth = originalLineWidth;

        // 3. Large Block M
        ctx.strokeRect(M_x, M_y, M_w, M_h);
        ctx.font = 'italic 28px "Times New Roman"';
        ctx.fillText('M', M_x + M_w / 2, M_y + M_h / 1.5);

        // 4. String (fixed connection to the wall as per problem description)
        const string_y = M_y + M_h - 60; // Positioned based on the image
        ctx.beginPath();
        ctx.moveTo(M_x + M_w, string_y);
        ctx.lineTo(wall_x, string_y);
        ctx.stroke();

        // 5. Small Block m
        ctx.strokeRect(m_x, m_y, m_w, m_h);
        ctx.font = 'italic 24px "Times New Roman"';
        ctx.fillText('m', m_x + m_w / 2, m_y + m_h / 2);

        // 6. Spring Assembly
        const spring_y = m_y + m_h / 2;
        const post_x = M_x + 20;
        
        // Spring mounting post
        ctx.beginPath();
        ctx.moveTo(post_x, M_y);
        ctx.lineTo(post_x, M_y - 40);
        ctx.stroke();

        // Spring
        const spring_start_x = post_x;
        const spring_end_plate_x = m_x - 70;
        const straight_len = 15;
        
        ctx.beginPath();
        // Start straight segment
        ctx.moveTo(spring_start_x, spring_y);
        ctx.lineTo(spring_start_x + straight_len, spring_y);
        
        // Coils
        const coils_start_x = spring_start_x + straight_len;
        const coils_end_x = spring_end_plate_x - straight_len;
        const num_coils = 4;
        const coil_radius = 12;
        const coil_section_width = (coils_end_x - coils_start_x);
        const coil_width = coil_section_width / num_coils;
        let current_x = coils_start_x;
        for (let i = 0; i < num_coils; i++) {
            ctx.arc(current_x + coil_width / 2, spring_y, coil_radius, Math.PI, 0, false);
            current_x += coil_width;
        }
        
        // End straight segment
        ctx.moveTo(coils_end_x, spring_y);
        ctx.lineTo(spring_end_plate_x, spring_y);
        ctx.stroke();

        // Spring end plate
        ctx.beginPath();
        ctx.moveTo(spring_end_plate_x, spring_y - 20);
        ctx.lineTo(spring_end_plate_x, spring_y + 20);
        ctx.stroke();

        // 7. Velocity Vector v0
        const arrow_y = m_y - 25;
        const arrow_start_x = m_x + m_w;
        const arrow_end_x = m_x + m_w - 100;
        
        drawArrow(ctx, arrow_start_x, arrow_y, arrow_end_x, arrow_y);
        
        // Label v0
        ctx.font = 'italic 22px "Times New Roman"';
        ctx.fillText('v', (arrow_start_x + arrow_end_x) / 2, arrow_y - 15);
        ctx.font = 'italic 16px "Times New Roman"';
        ctx.fillText('0', (arrow_start_x + arrow_end_x) / 2 + 8, arrow_y - 11);

        // 8. Caption
        ctx.font = '20px "SimSun", "Songti SC", sans-serif';
        ctx.fillStyle = 'black';
        ctx.fillText('力图 3.21.1', canvas.width / 2, ground_y + 40);

    </script>
</body>
</html>